package com.leon.datalink.core.persistence;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 持久化存储管理器
 * 
 * 管理不同类型的持久化存储实现（文件系统、PostgreSQL等）
 * 
 * @author DataLink Team
 * @version 1.0.0
 */
public class PersistenceStorageManager {
    
    private static final Logger logger = LoggerFactory.getLogger(PersistenceStorageManager.class);
    
    private static PersistenceStorageManager instance;
    
    // 存储类型枚举
    public enum StorageType {
        FILE("file", "基于文件系统的持久化存储"),
        POSTGRES("postgres", "基于PostgreSQL数据库的持久化存储"),
        LMDB("lmdb", "基于LMDB的持久化存储");
        
        private final String code;
        private final String description;
        
        StorageType(String code, String description) {
            this.code = code;
            this.description = description;
        }
        
        public String getCode() {
            return code;
        }
        
        public String getDescription() {
            return description;
        }
        
        public static StorageType fromCode(String code) {
            for (StorageType type : values()) {
                if (type.code.equals(code)) {
                    return type;
                }
            }
            return FILE; // 默认使用文件系统
        }
    }
    
    // 存储配置信息
    public static class StorageConfig {
        private StorageType type;
        private Map<String, String> properties;
        
        public StorageConfig(StorageType type) {
            this.type = type;
            this.properties = new HashMap<>();
        }
        
        public StorageType getType() {
            return type;
        }
        
        public void setType(StorageType type) {
            this.type = type;
        }
        
        public Map<String, String> getProperties() {
            return properties;
        }
        
        public void setProperty(String key, String value) {
            properties.put(key, value);
        }
        
        public String getProperty(String key) {
            return properties.get(key);
        }
        
        public String getProperty(String key, String defaultValue) {
            return properties.getOrDefault(key, defaultValue);
        }
    }
    
    private StorageConfig currentConfig;
    
    private PersistenceStorageManager() {
        // 初始化默认配置
        initializeDefaultConfig();
    }
    
    public static synchronized PersistenceStorageManager getInstance() {
        if (instance == null) {
            instance = new PersistenceStorageManager();
        }
        return instance;
    }
    
    /**
     * 初始化默认配置
     */
    private void initializeDefaultConfig() {
        // 从系统属性获取存储类型
        String storageTypeStr = System.getProperty("datalink.persistence.storage.type", "file");
        StorageType storageType = StorageType.fromCode(storageTypeStr);
        
        currentConfig = new StorageConfig(storageType);
        
        // 根据存储类型设置默认属性
        switch (storageType) {
            case FILE:
                initializeFileConfig();
                break;
            case POSTGRES:
                initializePostgresConfig();
                break;
            case LMDB:
                initializeLmdbConfig();
                break;
        }
        
        logger.info("初始化持久化存储配置: {}", storageType.getDescription());
    }
    
    /**
     * 初始化文件系统配置
     */
    private void initializeFileConfig() {
        currentConfig.setProperty("storage.path", 
            System.getProperty("datalink.persistence.storage.path", "data/persistence"));
        currentConfig.setProperty("journal.dir", "journal");
        currentConfig.setProperty("snapshot.dir", "snapshots");
    }
    
    /**
     * 初始化PostgreSQL配置
     */
    private void initializePostgresConfig() {
        currentConfig.setProperty("postgres.host", 
            System.getProperty("datalink.persistence.postgres.host", "localhost"));
        currentConfig.setProperty("postgres.port", 
            System.getProperty("datalink.persistence.postgres.port", "5432"));
        currentConfig.setProperty("postgres.database", 
            System.getProperty("datalink.persistence.postgres.database", "datalink"));
        currentConfig.setProperty("postgres.username", 
            System.getProperty("datalink.persistence.postgres.username", "datalink"));
        currentConfig.setProperty("postgres.password", 
            System.getProperty("datalink.persistence.postgres.password", "datalink"));
        currentConfig.setProperty("journal.table", "datalink_journal");
        currentConfig.setProperty("snapshot.table", "datalink_snapshots");
    }
    
    /**
     * 初始化LMDB配置
     */
    private void initializeLmdbConfig() {
        currentConfig.setProperty("lmdb.path", 
            System.getProperty("datalink.persistence.lmdb.path", "data/lmdb"));
        currentConfig.setProperty("lmdb.maxSize", 
            System.getProperty("datalink.persistence.lmdb.maxSize", "1GB"));
    }
    
    /**
     * 获取当前存储配置
     */
    public StorageConfig getCurrentConfig() {
        return currentConfig;
    }
    
    /**
     * 设置存储配置
     */
    public void setStorageConfig(StorageConfig config) {
        this.currentConfig = config;
        logger.info("更新持久化存储配置: {}", config.getType().getDescription());
    }
    
    /**
     * 获取Journal插件类名
     */
    public String getJournalPluginClass() {
        switch (currentConfig.getType()) {
            case FILE:
                return "com.leon.datalink.core.persistence.plugin.LmdbJournalPlugin";
            case POSTGRES:
                return "com.leon.datalink.core.persistence.plugin.PostgresJournalPlugin";
            case LMDB:
                return "com.leon.datalink.core.persistence.plugin.LmdbJournalPlugin";
            default:
                return "com.leon.datalink.core.persistence.plugin.LmdbJournalPlugin";
        }
    }
    
    /**
     * 获取Snapshot插件类名
     */
    public String getSnapshotPluginClass() {
        switch (currentConfig.getType()) {
            case FILE:
                return "com.leon.datalink.core.persistence.plugin.LmdbSnapshotPlugin";
            case POSTGRES:
                return "com.leon.datalink.core.persistence.plugin.PostgresSnapshotPlugin";
            case LMDB:
                return "com.leon.datalink.core.persistence.plugin.LmdbSnapshotPlugin";
            default:
                return "com.leon.datalink.core.persistence.plugin.LmdbSnapshotPlugin";
        }
    }
    
    /**
     * 获取配置文件路径
     */
    public String getConfigFilePath() {
        switch (currentConfig.getType()) {
            case FILE:
                return "persistence.conf";
            case POSTGRES:
                return "persistence-postgres.conf";
            case LMDB:
                return "persistence.conf";
            default:
                return "persistence.conf";
        }
    }
    
    /**
     * 验证存储配置
     */
    public boolean validateConfig() {
        try {
            switch (currentConfig.getType()) {
                case FILE:
                    return validateFileConfig();
                case POSTGRES:
                    return validatePostgresConfig();
                case LMDB:
                    return validateLmdbConfig();
                default:
                    return false;
            }
        } catch (Exception e) {
            logger.error("存储配置验证失败", e);
            return false;
        }
    }
    
    /**
     * 验证文件系统配置
     */
    private boolean validateFileConfig() {
        String storagePath = currentConfig.getProperty("storage.path");
        if (storagePath == null || storagePath.trim().isEmpty()) {
            logger.error("文件系统存储路径未配置");
            return false;
        }
        
        logger.info("✓ 文件系统配置验证通过: {}", storagePath);
        return true;
    }
    
    /**
     * 验证PostgreSQL配置
     */
    private boolean validatePostgresConfig() {
        String host = currentConfig.getProperty("postgres.host");
        String port = currentConfig.getProperty("postgres.port");
        String database = currentConfig.getProperty("postgres.database");
        String username = currentConfig.getProperty("postgres.username");
        String password = currentConfig.getProperty("postgres.password");
        
        if (host == null || host.trim().isEmpty()) {
            logger.error("PostgreSQL主机地址未配置");
            return false;
        }
        
        if (port == null || port.trim().isEmpty()) {
            logger.error("PostgreSQL端口未配置");
            return false;
        }
        
        if (database == null || database.trim().isEmpty()) {
            logger.error("PostgreSQL数据库名未配置");
            return false;
        }
        
        if (username == null || username.trim().isEmpty()) {
            logger.error("PostgreSQL用户名未配置");
            return false;
        }
        
        if (password == null) {
            logger.error("PostgreSQL密码未配置");
            return false;
        }
        
        logger.info("✓ PostgreSQL配置验证通过: {}:{}/{}", host, port, database);
        return true;
    }
    
    /**
     * 验证LMDB配置
     */
    private boolean validateLmdbConfig() {
        String lmdbPath = currentConfig.getProperty("lmdb.path");
        if (lmdbPath == null || lmdbPath.trim().isEmpty()) {
            logger.error("LMDB存储路径未配置");
            return false;
        }
        
        logger.info("✓ LMDB配置验证通过: {}", lmdbPath);
        return true;
    }
    
    /**
     * 获取存储状态信息
     */
    public Map<String, Object> getStorageStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("type", currentConfig.getType().getCode());
        status.put("description", currentConfig.getType().getDescription());
        status.put("properties", new HashMap<>(currentConfig.getProperties()));
        status.put("journalPlugin", getJournalPluginClass());
        status.put("snapshotPlugin", getSnapshotPluginClass());
        status.put("configFile", getConfigFilePath());
        status.put("valid", validateConfig());
        
        return status;
    }
    
    /**
     * 切换存储类型
     */
    public boolean switchStorageType(StorageType newType) {
        try {
            StorageType oldType = currentConfig.getType();
            
            // 创建新配置
            StorageConfig newConfig = new StorageConfig(newType);
            
            // 根据新类型初始化配置
            switch (newType) {
                case FILE:
                    initializeFileConfig();
                    break;
                case POSTGRES:
                    initializePostgresConfig();
                    break;
                case LMDB:
                    initializeLmdbConfig();
                    break;
            }
            
            // 验证新配置
            if (!validateConfig()) {
                logger.error("新存储类型配置验证失败: {}", newType);
                return false;
            }
            
            // 应用新配置
            this.currentConfig = newConfig;
            
            logger.info("存储类型切换成功: {} -> {}", oldType, newType);
            return true;
            
        } catch (Exception e) {
            logger.error("存储类型切换失败", e);
            return false;
        }
    }
}
